package com.cskaoyan.javase.oop2._2polymorphic._3exercise;
/**
 * 读程序题
 * 对于对象名点成员方法的调用机制:
 *      编译时看左边(引用),运行时看右边(对象)
 * 编译时看左边,意味着方法的访问范围就只限于引用的类型
 * 具体来说:
 *      如果引用是父类类型,那么访问范围就是父类.
 *      子类独有的方法,看都不需要看,因为肯定访问不到.
 *      但是对于那些在子类中重写的方法,要在调用时关注对象,看对象是否是子类类型,如果是,就要体现出子类的行为
 *
 *      如果引用是子类类型,那么访问范围就是父类 + 子类
 *      这意味方法的访问要看子类的,同时不要忘记看父类的
 *
 *
 * 除了以上原则,还有一个问题:
 * 方法的重载 导致方法的调用匹配可以有多种
 * 这时要遵循就近原则
 * 能够直接匹配就直接匹配
 * 如果需要转换才能匹配,要选择转换次数少的
 *
 * @since 16:24
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo2 {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();
        B b = new B();
        C c = new C();
        D d = new D();
        // AA
        System.out.println("1--" + a1.show(b));
        // AA
        System.out.println("2--" + a1.show(c));
        // AD
        System.out.println("3--" + a1.show(d));

        // BA
        System.out.println("4--" + a2.show(b));
        // BA
        System.out.println("5--" + a2.show(c));
        // AD
        System.out.println("6--" + a2.show(d));

        // BB
        System.out.println("7--" + b.show(b));
        // BB
        System.out.println("8--" + b.show(c));
        // AD
        System.out.println("9--" + b.show(d));
    }
}

class A {
    // 以下两个show方法,构成方法的重载
    // 这是父类中独有的show方法
    public String show(D obj) {
        return ("A and D");
    }

    // 这是父类中被子类重写的show方法
    public String show(A obj) {
        return ("A and A");
    }
}

class B extends A {
    // 这是子类中独有的show方法
    public String show(B obj) {
        return ("B and B");
    }

    // 这是子类中重写自父类的show方法
    @Override
    public String show(A obj) {
        return ("B and A");
    }
}

class C extends B {
}

class D extends B {
}